{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "plt.rcParams['figure.figsize'] = [10, 5]\n",
    "\n",
    "import pdb\n",
    "\n",
    "import simpy\n",
    "import random\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A simpler example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def car(env, num):\n",
    "     while True:\n",
    "         print('Car # %d: Park at at %d' % (num, env.now))\n",
    "         parking_duration = 2 + random.randint(0, 3)\n",
    "         yield env.timeout(parking_duration)\n",
    "\n",
    "         print('Car # %d: Drive at %d'   % (num, env.now))\n",
    "         trip_duration = 20 + random.randint(0, 6)\n",
    "         yield env.timeout(trip_duration)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Simulate just one car"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Car # 1: Park at at 0\n",
      "Car # 1: Drive at 4\n",
      "Car # 1: Park at at 27\n",
      "Car # 1: Drive at 31\n",
      "Car # 1: Park at at 55\n",
      "Car # 1: Drive at 58\n",
      "Car # 1: Park at at 79\n",
      "Car # 1: Drive at 82\n",
      "Car # 1: Park at at 102\n",
      "Car # 1: Drive at 105\n",
      "Car # 1: Park at at 126\n",
      "Car # 1: Drive at 128\n",
      "Car # 1: Park at at 149\n"
     ]
    }
   ],
   "source": [
    "env = simpy.Environment()\n",
    "env.process(car(env, 1))\n",
    "env.run(until=150)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Car # 1: Park at at 0\n",
      "Car # 2: Park at at 0\n",
      "Car # 3: Park at at 0\n",
      "Car # 1: Drive at 4\n",
      "Car # 2: Drive at 4\n",
      "Car # 3: Drive at 4\n",
      "Car # 3: Park at at 24\n",
      "Car # 3: Drive at 26\n",
      "Car # 2: Park at at 28\n",
      "Car # 1: Park at at 29\n",
      "Car # 2: Drive at 31\n",
      "Car # 1: Drive at 33\n",
      "Car # 3: Park at at 49\n",
      "Car # 2: Park at at 51\n",
      "Car # 1: Park at at 53\n",
      "Car # 3: Drive at 53\n",
      "Car # 2: Drive at 55\n",
      "Car # 1: Drive at 56\n",
      "Car # 3: Park at at 76\n",
      "Car # 2: Park at at 78\n",
      "Car # 3: Drive at 79\n",
      "Car # 1: Park at at 80\n",
      "Car # 2: Drive at 81\n",
      "Car # 1: Drive at 83\n",
      "Car # 2: Park at at 102\n",
      "Car # 1: Park at at 103\n",
      "Car # 3: Park at at 104\n",
      "Car # 2: Drive at 106\n",
      "Car # 3: Drive at 106\n",
      "Car # 1: Drive at 108\n",
      "Car # 2: Park at at 126\n",
      "Car # 2: Drive at 130\n",
      "Car # 3: Park at at 131\n",
      "Car # 3: Drive at 133\n",
      "Car # 1: Park at at 134\n",
      "Car # 1: Drive at 138\n"
     ]
    }
   ],
   "source": [
    "env = simpy.Environment()\n",
    "env.process(car(env, 1))\n",
    "env.process(car(env, 2))\n",
    "env.process(car(env, 3))\n",
    "env.run(until=150)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A more complex ecology inspired example with a scarce resource"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "A forest has 3 lakes, each of which can accommodate 2 individual animals at once. \n",
    "There are prey and predator animals. When not drinking, the predator animals eat prey\n",
    "animals when the prey cross their paths. When not drinking, the prey animals\n",
    "are either reproducing  (asexually) or bumping into predators and being eaten.\n",
    "\"\"\"\n",
    "\n",
    "MTTD               = 600.0 # mean time before an animal needs to drink after drinking\n",
    "DRINK_MIN          = 120.0 # min time between drinks from the lake\n",
    "DRINK_MEAN         = 5.0\n",
    "DRINK_SIGMA        = 1.0\n",
    "REPRO_MEAN         = 200.0 # mean time to reproduce\n",
    "REPRO_SIGMA        = 20.0 # sd of time to reproduce\n",
    "EAT_MEAN           = 10.0 # mean time to eat prey\n",
    "EAT_SIGMA          = 1.0 # sd of time to eat prety\n",
    "TREE_GROW_DURATION = 4000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def time_to_(activity):\n",
    "    activity_time = 1.0\n",
    "    if activity == 'go_to_lake_':\n",
    "        activity_time = random.expovariate(MTTD) + DRINK_MIN\n",
    "    elif activity == 'drink':\n",
    "        activity_time =  random.normalvariate(DRINK_MEAN, DRINK_SIGMA)\n",
    "    elif activity == 'repro':\n",
    "        activity_time =  random.normalvariate(REPRO_MEAN, REPRO_SIGMA)\n",
    "    elif activity == 'eat':\n",
    "        activity_time =  random.normalvariate(EAT_MEAN, EAT_SIGMA)\n",
    "    return max(activity_time, 1.0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Animal(object):\n",
    "    def __init__(self, env, name, lake):\n",
    "        self.env            = env\n",
    "        self.name           = name\n",
    "        self.offspring_made = 0\n",
    "        self.thirsty        = False\n",
    "\n",
    "        self.process = env.process(self.living(lake))\n",
    "        env.process(self.drink_from_lake())\n",
    "\n",
    "    def living(self, lake):\n",
    "        while True:\n",
    "            # Start making a new part\n",
    "            done_in = time_to_('eat')\n",
    "            while done_in:\n",
    "                try:\n",
    "                    # Working on the part\n",
    "                    start = self.env.now\n",
    "                    #print(\"started eating = %f and time remaining = %f\" % (self.env.now, done_in))\n",
    "                    yield self.env.timeout(done_in)\n",
    "                    done_in = 0  # Set to 0 to exit while loop.\n",
    "                except simpy.Interrupt:\n",
    "                    self.thirsty = True\n",
    "                    done_in -= self.env.now - start  # How much time left?\n",
    "\n",
    "                    # Seek access to the lake, either by waiting for another\n",
    "                    # animal to finish or displacing a feeding sapling\n",
    "                    with lake.request(priority=1) as req:\n",
    "                        yield req\n",
    "                        drink_time = time_to_('drink')\n",
    "                        #print(\"started drinking = %f and time remaining = %f\" % (self.env.now, drink_time))\n",
    "                        yield self.env.timeout(drink_time)\n",
    "                    self.thirsty = False\n",
    "\n",
    "            # Start making a new part\n",
    "            done_in = time_to_('repro')\n",
    "            while done_in:\n",
    "                try:\n",
    "                    # Working on the part\n",
    "                    start = self.env.now\n",
    "                    #print(\"started breeding = %f and time remaining = %f\" % (self.env.now, done_in))\n",
    "                    yield self.env.timeout(done_in)\n",
    "                    #print(\"MADE A BABY\")\n",
    "                    self.offspring_made += 1\n",
    "\n",
    "                    done_in = 0  # Set to 0 to exit while loop.\n",
    "\n",
    "                except simpy.Interrupt:\n",
    "                    self.thirsty = True\n",
    "                    done_in -= self.env.now - start  # How much time left?\n",
    "\n",
    "                    # Seek access to the lake, either by waiting for another\n",
    "                    # animal to finish or displacing a feeding sapling\n",
    "                    with lake.request(priority=1) as req:\n",
    "                        yield req\n",
    "                        drink_time = time_to_('drink')\n",
    "                        #print(\"started drinking = %f and time remaining = %f\" % (self.env.now, drink_time))\n",
    "                        yield self.env.timeout(drink_time)\n",
    "\n",
    "                    self.thirsty = False\n",
    "                    \n",
    "    def drink_from_lake(self):\n",
    "        \"\"\"go drink at capacity limited lake from time to time\"\"\"\n",
    "        while True:\n",
    "            yield self.env.timeout(30)\n",
    "            ##yield self.env.timeout(time_to_('go_to_lake'))\n",
    "            if not self.thirsty:\n",
    "                # Only drink if currently not drinking from lake\n",
    "                self.process.interrupt()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def other_water_uses(env, lake):\n",
    "    \"\"\"The lake also nourishes plants\"\"\"\n",
    "    while True:\n",
    "        # Start a new job\n",
    "        done_in = TREE_GROW_DURATION\n",
    "        while done_in:\n",
    "            # Retry the job until it is done.\n",
    "            # It's priority is lower than that of machine repairs.\n",
    "            with lake.request(priority=2) as req:\n",
    "                yield req\n",
    "                try:\n",
    "                    start = env.now\n",
    "                    yield env.timeout(done_in)\n",
    "                    TREES_GROWN = TREES_GROWN + 1\n",
    "                    done_in = 0\n",
    "                except simpy.Interrupt:\n",
    "                    done_in -= env.now - start\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lake results\n",
      "Animal 0 made 4 offspring.\n",
      "Animal 1 made 3 offspring.\n"
     ]
    }
   ],
   "source": [
    "# Setup and start the simulation\n",
    "SIM_TIME = 1000\n",
    "RANDOM_SEED = 1142\n",
    "TREES_GROWN = 0\n",
    "LAKE_CAPACITY = 6\n",
    "NUM_ANIMALS = 2\n",
    "\n",
    "random.seed(RANDOM_SEED)  # This helps reproducing the results\n",
    "\n",
    "# Create an environment and start the setup process\n",
    "env = simpy.Environment()\n",
    "\n",
    "lake = simpy.PreemptiveResource(env, capacity=LAKE_CAPACITY)\n",
    "animals = [Animal(env, 'Animal %d' % i, lake) for i in range(NUM_ANIMALS)]\n",
    "\n",
    "env.process(other_water_uses(env, lake))\n",
    "\n",
    "# Execute!\n",
    "env.run(until=SIM_TIME)\n",
    "\n",
    "# Analyis/results\n",
    "print('Lake results')\n",
    "for animal in animals:\n",
    "    print('%s made %d offspring.' % (animal.name, animal.offspring_made))\n",
    "    \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise: consider an extreme situation that might lead to fewer offspring even as there are more animals. How can we test this by modifying the code above?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lake results\n",
      "Animal 0 made 0 offspring.\n",
      "Animal 1 made 0 offspring.\n",
      "Animal 2 made 0 offspring.\n",
      "Animal 3 made 0 offspring.\n",
      "Animal 4 made 0 offspring.\n",
      "Animal 5 made 0 offspring.\n",
      "Animal 6 made 0 offspring.\n",
      "Animal 7 made 0 offspring.\n",
      "Animal 8 made 0 offspring.\n",
      "Animal 9 made 0 offspring.\n",
      "Animal 10 made 0 offspring.\n",
      "Animal 11 made 0 offspring.\n",
      "Animal 12 made 0 offspring.\n",
      "Animal 13 made 0 offspring.\n",
      "Animal 14 made 0 offspring.\n",
      "Animal 15 made 0 offspring.\n",
      "Animal 16 made 0 offspring.\n",
      "Animal 17 made 0 offspring.\n",
      "Animal 18 made 0 offspring.\n",
      "Animal 19 made 0 offspring.\n",
      "Animal 20 made 0 offspring.\n",
      "Animal 21 made 0 offspring.\n",
      "Animal 22 made 0 offspring.\n",
      "Animal 23 made 0 offspring.\n",
      "Animal 24 made 0 offspring.\n",
      "Animal 25 made 0 offspring.\n",
      "Animal 26 made 0 offspring.\n",
      "Animal 27 made 0 offspring.\n",
      "Animal 28 made 0 offspring.\n",
      "Animal 29 made 0 offspring.\n",
      "Animal 30 made 0 offspring.\n",
      "Animal 31 made 0 offspring.\n",
      "Animal 32 made 0 offspring.\n",
      "Animal 33 made 0 offspring.\n",
      "Animal 34 made 0 offspring.\n",
      "Animal 35 made 0 offspring.\n",
      "Animal 36 made 0 offspring.\n",
      "Animal 37 made 0 offspring.\n",
      "Animal 38 made 0 offspring.\n",
      "Animal 39 made 0 offspring.\n",
      "Animal 40 made 0 offspring.\n",
      "Animal 41 made 0 offspring.\n",
      "Animal 42 made 0 offspring.\n",
      "Animal 43 made 0 offspring.\n",
      "Animal 44 made 0 offspring.\n",
      "Animal 45 made 0 offspring.\n",
      "Animal 46 made 0 offspring.\n",
      "Animal 47 made 0 offspring.\n",
      "Animal 48 made 0 offspring.\n",
      "Animal 49 made 0 offspring.\n",
      "Animal 50 made 0 offspring.\n",
      "Animal 51 made 0 offspring.\n",
      "Animal 52 made 0 offspring.\n",
      "Animal 53 made 0 offspring.\n",
      "Animal 54 made 0 offspring.\n",
      "Animal 55 made 0 offspring.\n",
      "Animal 56 made 0 offspring.\n",
      "Animal 57 made 0 offspring.\n",
      "Animal 58 made 0 offspring.\n",
      "Animal 59 made 0 offspring.\n",
      "Animal 60 made 0 offspring.\n",
      "Animal 61 made 0 offspring.\n",
      "Animal 62 made 0 offspring.\n",
      "Animal 63 made 0 offspring.\n",
      "Animal 64 made 0 offspring.\n",
      "Animal 65 made 0 offspring.\n",
      "Animal 66 made 0 offspring.\n",
      "Animal 67 made 0 offspring.\n",
      "Animal 68 made 0 offspring.\n",
      "Animal 69 made 0 offspring.\n",
      "Animal 70 made 0 offspring.\n",
      "Animal 71 made 0 offspring.\n",
      "Animal 72 made 0 offspring.\n",
      "Animal 73 made 0 offspring.\n",
      "Animal 74 made 0 offspring.\n",
      "Animal 75 made 0 offspring.\n",
      "Animal 76 made 0 offspring.\n",
      "Animal 77 made 0 offspring.\n",
      "Animal 78 made 0 offspring.\n",
      "Animal 79 made 0 offspring.\n",
      "Animal 80 made 0 offspring.\n",
      "Animal 81 made 0 offspring.\n",
      "Animal 82 made 0 offspring.\n",
      "Animal 83 made 0 offspring.\n",
      "Animal 84 made 0 offspring.\n",
      "Animal 85 made 0 offspring.\n",
      "Animal 86 made 0 offspring.\n",
      "Animal 87 made 0 offspring.\n",
      "Animal 88 made 0 offspring.\n",
      "Animal 89 made 0 offspring.\n",
      "Animal 90 made 0 offspring.\n",
      "Animal 91 made 0 offspring.\n",
      "Animal 92 made 0 offspring.\n",
      "Animal 93 made 0 offspring.\n",
      "Animal 94 made 0 offspring.\n",
      "Animal 95 made 0 offspring.\n",
      "Animal 96 made 0 offspring.\n",
      "Animal 97 made 0 offspring.\n",
      "Animal 98 made 0 offspring.\n",
      "Animal 99 made 0 offspring.\n",
      "Animal 100 made 0 offspring.\n",
      "Animal 101 made 0 offspring.\n",
      "Animal 102 made 0 offspring.\n",
      "Animal 103 made 0 offspring.\n",
      "Animal 104 made 0 offspring.\n",
      "Animal 105 made 0 offspring.\n",
      "Animal 106 made 0 offspring.\n",
      "Animal 107 made 0 offspring.\n",
      "Animal 108 made 0 offspring.\n",
      "Animal 109 made 0 offspring.\n",
      "Animal 110 made 0 offspring.\n",
      "Animal 111 made 0 offspring.\n",
      "Animal 112 made 0 offspring.\n",
      "Animal 113 made 0 offspring.\n",
      "Animal 114 made 0 offspring.\n",
      "Animal 115 made 0 offspring.\n",
      "Animal 116 made 0 offspring.\n",
      "Animal 117 made 0 offspring.\n",
      "Animal 118 made 0 offspring.\n",
      "Animal 119 made 0 offspring.\n",
      "Animal 120 made 0 offspring.\n",
      "Animal 121 made 0 offspring.\n",
      "Animal 122 made 0 offspring.\n",
      "Animal 123 made 0 offspring.\n",
      "Animal 124 made 0 offspring.\n",
      "Animal 125 made 0 offspring.\n",
      "Animal 126 made 0 offspring.\n",
      "Animal 127 made 0 offspring.\n",
      "Animal 128 made 0 offspring.\n",
      "Animal 129 made 0 offspring.\n",
      "Animal 130 made 0 offspring.\n",
      "Animal 131 made 0 offspring.\n",
      "Animal 132 made 0 offspring.\n",
      "Animal 133 made 0 offspring.\n",
      "Animal 134 made 0 offspring.\n",
      "Animal 135 made 0 offspring.\n",
      "Animal 136 made 0 offspring.\n",
      "Animal 137 made 0 offspring.\n",
      "Animal 138 made 0 offspring.\n",
      "Animal 139 made 0 offspring.\n",
      "Animal 140 made 0 offspring.\n",
      "Animal 141 made 0 offspring.\n",
      "Animal 142 made 0 offspring.\n",
      "Animal 143 made 0 offspring.\n",
      "Animal 144 made 0 offspring.\n",
      "Animal 145 made 0 offspring.\n",
      "Animal 146 made 0 offspring.\n",
      "Animal 147 made 0 offspring.\n",
      "Animal 148 made 0 offspring.\n",
      "Animal 149 made 0 offspring.\n",
      "Animal 150 made 0 offspring.\n",
      "Animal 151 made 0 offspring.\n",
      "Animal 152 made 0 offspring.\n",
      "Animal 153 made 0 offspring.\n",
      "Animal 154 made 0 offspring.\n",
      "Animal 155 made 0 offspring.\n",
      "Animal 156 made 0 offspring.\n",
      "Animal 157 made 0 offspring.\n",
      "Animal 158 made 0 offspring.\n",
      "Animal 159 made 0 offspring.\n",
      "Animal 160 made 0 offspring.\n",
      "Animal 161 made 0 offspring.\n",
      "Animal 162 made 0 offspring.\n",
      "Animal 163 made 0 offspring.\n",
      "Animal 164 made 0 offspring.\n",
      "Animal 165 made 0 offspring.\n",
      "Animal 166 made 0 offspring.\n",
      "Animal 167 made 0 offspring.\n",
      "Animal 168 made 0 offspring.\n",
      "Animal 169 made 0 offspring.\n",
      "Animal 170 made 0 offspring.\n",
      "Animal 171 made 0 offspring.\n",
      "Animal 172 made 0 offspring.\n",
      "Animal 173 made 0 offspring.\n",
      "Animal 174 made 0 offspring.\n",
      "Animal 175 made 0 offspring.\n",
      "Animal 176 made 0 offspring.\n",
      "Animal 177 made 0 offspring.\n",
      "Animal 178 made 0 offspring.\n",
      "Animal 179 made 0 offspring.\n",
      "Animal 180 made 0 offspring.\n",
      "Animal 181 made 0 offspring.\n",
      "Animal 182 made 0 offspring.\n",
      "Animal 183 made 0 offspring.\n",
      "Animal 184 made 0 offspring.\n",
      "Animal 185 made 0 offspring.\n",
      "Animal 186 made 0 offspring.\n",
      "Animal 187 made 0 offspring.\n",
      "Animal 188 made 0 offspring.\n",
      "Animal 189 made 0 offspring.\n",
      "Animal 190 made 0 offspring.\n",
      "Animal 191 made 0 offspring.\n",
      "Animal 192 made 0 offspring.\n",
      "Animal 193 made 0 offspring.\n",
      "Animal 194 made 0 offspring.\n",
      "Animal 195 made 0 offspring.\n",
      "Animal 196 made 0 offspring.\n",
      "Animal 197 made 0 offspring.\n",
      "Animal 198 made 0 offspring.\n",
      "Animal 199 made 0 offspring.\n"
     ]
    }
   ],
   "source": [
    "NUM_ANIMALS = 200\n",
    "\n",
    "random.seed(RANDOM_SEED)  # This helps reproducing the results\n",
    "\n",
    "# Create an environment and start the setup process\n",
    "env = simpy.Environment()\n",
    "\n",
    "lake = simpy.PreemptiveResource(env, capacity=LAKE_CAPACITY)\n",
    "animals = [Animal(env, 'Animal %d' % i, lake) for i in range(NUM_ANIMALS)]\n",
    "\n",
    "env.process(other_water_uses(env, lake))\n",
    "\n",
    "# Execute!\n",
    "env.run(until=SIM_TIME)\n",
    "\n",
    "# Analyis/results\n",
    "print('Lake results')\n",
    "for animal in animals:\n",
    "    print('%s made %d offspring.' % (animal.name, animal.offspring_made))\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise: How would you determine the number of offspring produced by the sim as a function of the number of animals?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7fd27e03f128>]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "num_offspring = []\n",
    "num_animals = [2, 10, 20, 50, 100, 150, 200]\n",
    "for num in num_animals:\n",
    "    # Create an environment and start the setup process\n",
    "    env = simpy.Environment()\n",
    "\n",
    "    lake = simpy.PreemptiveResource(env, capacity=LAKE_CAPACITY)\n",
    "    animals = [Animal(env, 'Animal %d' % i, lake) for i in range(num)]\n",
    "\n",
    "    env.process(other_water_uses(env, lake))\n",
    "\n",
    "    # Execute!\n",
    "    env.run(until=SIM_TIME)\n",
    "\n",
    "    this_offspring = 0\n",
    "    for animal in animals:\n",
    "        this_offspring += animal.offspring_made\n",
    "    num_offspring.append(this_offspring)\n",
    "    \n",
    "plt.plot(num_animals, num_offspring)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[7, 32, 53, 63, 41, 3, 0]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "num_offspring"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise: Can we put in some 'learning' in this model? \n",
    "#### How can we code animals that get smarter over time?\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "class SmartAnimal(object):\n",
    "    def __init__(self, env, name, lake):\n",
    "        self.env            = env\n",
    "        self.name           = name\n",
    "        self.offspring_made = 0\n",
    "        self.thirsty        = False\n",
    "        self.experience     = 0\n",
    "\n",
    "        self.process = env.process(self.living(lake))\n",
    "        env.process(self.drink_from_lake())\n",
    "\n",
    "    def living(self, lake):\n",
    "        while True:\n",
    "            # Start making a new part\n",
    "            done_in = time_to_('eat')\n",
    "            while done_in:\n",
    "                try:\n",
    "                    # Working on the part\n",
    "                    start = self.env.now\n",
    "                    #print(\"started eating = %f and time remaining = %f\" % (self.env.now, done_in))\n",
    "                    yield self.env.timeout(done_in)\n",
    "                    done_in = 0  # Set to 0 to exit while loop.\n",
    "                except simpy.Interrupt:\n",
    "                    self.experience += 1\n",
    "                    self.thirsty     = True\n",
    "                    done_in         -= self.env.now - start  # How much time left?\n",
    "\n",
    "                    if self.experience > 2:\n",
    "                        self.experience -= 1\n",
    "                        print(\"with experience, decided to skip drinking\")\n",
    "                    else:\n",
    "                    \n",
    "                        # Seek access to the lake, either by waiting for another\n",
    "                        # animal to finish or displacing a feeding sapling\n",
    "                        with lake.request(priority=1) as req:\n",
    "                            yield req\n",
    "                            drink_time = time_to_('drink')\n",
    "                            #print(\"started drinking = %f and time remaining = %f\" % (self.env.now, drink_time))\n",
    "                            yield self.env.timeout(drink_time)\n",
    "                    self.thirsty = False\n",
    "\n",
    "            # Start making a new part\n",
    "            done_in = time_to_('repro')\n",
    "            while done_in:\n",
    "                try:\n",
    "                    # Working on the part\n",
    "                    start = self.env.now\n",
    "                    #print(\"started breeding = %f and time remaining = %f\" % (self.env.now, done_in))\n",
    "                    yield self.env.timeout(done_in)\n",
    "                    #print(\"MADE A BABY\")\n",
    "                    self.offspring_made += 1\n",
    "\n",
    "                    done_in = 0  # Set to 0 to exit while loop.\n",
    "\n",
    "                except simpy.Interrupt:\n",
    "                    self.thirsty = True\n",
    "                    done_in -= self.env.now - start  # How much time left?\n",
    "\n",
    "                    # Seek access to the lake, either by waiting for another\n",
    "                    # animal to finish or displacing a feeding sapling\n",
    "                    with lake.request(priority=1) as req:\n",
    "                        yield req\n",
    "                        drink_time = time_to_('drink')\n",
    "                        #print(\"started drinking = %f and time remaining = %f\" % (self.env.now, drink_time))\n",
    "                        yield self.env.timeout(drink_time)\n",
    "\n",
    "                    self.thirsty = False\n",
    "                    \n",
    "    def drink_from_lake(self):\n",
    "        \"\"\"go drink at capacity limited lake from time to time\"\"\"\n",
    "        while True:\n",
    "            yield self.env.timeout(30)\n",
    "            ##yield self.env.timeout(time_to_('go_to_lake'))\n",
    "            if not self.thirsty:\n",
    "                # Only drink if currently not drinking from lake\n",
    "                self.process.interrupt()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7fd2802855c0>]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "num_offspring = []\n",
    "num_animals = [2, 10, 20, 50, 100, 150, 200]\n",
    "for num in num_animals:\n",
    "    # Create an environment and start the setup process\n",
    "    env = simpy.Environment()\n",
    "\n",
    "    lake = simpy.PreemptiveResource(env, capacity=LAKE_CAPACITY)\n",
    "    animals = [SmartAnimal(env, 'Animal %d' % i, lake) for i in range(num)]\n",
    "\n",
    "    env.process(other_water_uses(env, lake))\n",
    "\n",
    "    # Execute!\n",
    "    env.run(until=SIM_TIME*3)\n",
    "\n",
    "    this_offspring = 0\n",
    "    for animal in animals:\n",
    "        this_offspring += animal.offspring_made\n",
    "    num_offspring.append(this_offspring)\n",
    "    \n",
    "plt.plot(num_animals, num_offspring)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[23, 108, 177, 248, 220, 203, 179]"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "num_offspring"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Can we think of a way so that some but not all animals get smarter/better over time?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "class SomeSmartAnimal(object):\n",
    "    def __init__(self, env, name, lake):\n",
    "        self.env            = env\n",
    "        self.name           = name\n",
    "        self.offspring_made = 0\n",
    "        self.thirsty        = False\n",
    "        self.experience     = 0\n",
    "        self.can_learn      = np.random.randint(0, 2)\n",
    "\n",
    "        self.process = env.process(self.living(lake))\n",
    "        env.process(self.drink_from_lake())\n",
    "\n",
    "    def living(self, lake):\n",
    "        while True:\n",
    "            # Start making a new part\n",
    "            done_in = time_to_('eat')\n",
    "            while done_in:\n",
    "                try:\n",
    "                    # Working on the part\n",
    "                    start = self.env.now\n",
    "                    #print(\"started eating = %f and time remaining = %f\" % (self.env.now, done_in))\n",
    "                    yield self.env.timeout(done_in)\n",
    "                    done_in = 0  # Set to 0 to exit while loop.\n",
    "                except simpy.Interrupt:\n",
    "                    if self.can_learn:\n",
    "                        self.experience += 1\n",
    "                        \n",
    "                    self.thirsty     = True\n",
    "                    done_in         -= self.env.now - start  # How much time left?\n",
    "\n",
    "                    if self.experience > 2:\n",
    "                        self.experience -= 1\n",
    "                        print(\"with experience, decided to skip drinking\")\n",
    "                    else:\n",
    "                    \n",
    "                        # Seek access to the lake, either by waiting for another\n",
    "                        # animal to finish or displacing a feeding sapling\n",
    "                        with lake.request(priority=1) as req:\n",
    "                            yield req\n",
    "                            drink_time = time_to_('drink')\n",
    "                            #print(\"started drinking = %f and time remaining = %f\" % (self.env.now, drink_time))\n",
    "                            yield self.env.timeout(drink_time)\n",
    "                    self.thirsty = False\n",
    "\n",
    "            # Start making a new part\n",
    "            done_in = time_to_('repro')\n",
    "            while done_in:\n",
    "                try:\n",
    "                    # Working on the part\n",
    "                    start = self.env.now\n",
    "                    #print(\"started breeding = %f and time remaining = %f\" % (self.env.now, done_in))\n",
    "                    yield self.env.timeout(done_in)\n",
    "                    #print(\"MADE A BABY\")\n",
    "                    self.offspring_made += 1\n",
    "\n",
    "                    done_in = 0  # Set to 0 to exit while loop.\n",
    "\n",
    "                except simpy.Interrupt:\n",
    "                    self.thirsty = True\n",
    "                    done_in -= self.env.now - start  # How much time left?\n",
    "\n",
    "                    # Seek access to the lake, either by waiting for another\n",
    "                    # animal to finish or displacing a feeding sapling\n",
    "                    with lake.request(priority=1) as req:\n",
    "                        yield req\n",
    "                        drink_time = time_to_('drink')\n",
    "                        #print(\"started drinking = %f and time remaining = %f\" % (self.env.now, drink_time))\n",
    "                        yield self.env.timeout(drink_time)\n",
    "\n",
    "                    self.thirsty = False\n",
    "                    \n",
    "    def drink_from_lake(self):\n",
    "        \"\"\"go drink at capacity limited lake from time to time\"\"\"\n",
    "        while True:\n",
    "            yield self.env.timeout(30)\n",
    "            ##yield self.env.timeout(time_to_('go_to_lake'))\n",
    "            if not self.thirsty:\n",
    "                # Only drink if currently not drinking from lake\n",
    "                self.process.interrupt()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n",
      "with experience, decided to skip drinking\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7fd27d5d4048>]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "num_offspring = []\n",
    "num_animals = [2, 10, 20, 50, 100, 150, 200]\n",
    "for num in num_animals:\n",
    "    # Create an environment and start the setup process\n",
    "    env = simpy.Environment()\n",
    "\n",
    "    lake = simpy.PreemptiveResource(env, capacity=LAKE_CAPACITY)\n",
    "    animals = [SomeSmartAnimal(env, 'Animal %d' % i, lake) for i in range(num)]\n",
    "\n",
    "    env.process(other_water_uses(env, lake))\n",
    "\n",
    "    # Execute!\n",
    "    env.run(until=SIM_TIME*3)\n",
    "\n",
    "    this_offspring = 0\n",
    "    for animal in animals:\n",
    "        this_offspring += animal.offspring_made\n",
    "    num_offspring.append(this_offspring)\n",
    "    \n",
    "plt.plot(num_animals, num_offspring)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[23, 108, 171, 241, 215, 205, 181]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "num_offspring"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise: Take a look at SimPy's API. How could we add a meaningful constraint to the water levels in lake?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
